import { useState } from 'react';
import {
    Button,
    Flex,
    Form,
    FormGroup,
    Tab,
    TabContent,
    Tabs,
    Text,
    TextArea,
} from '@patternfly/react-core';
import { useFormik } from 'formik';
import type { FormikHelpers } from 'formik';
import type * as yup from 'yup';

import type { ExceptionValues, ScopeContext } from './utils';
import ExceptionScopeField, { ALL } from './ExceptionScopeField';
import CveSelections from './CveSelections';
import type { CveSelectionsProps } from './CveSelections';
import ExpiryField from './ExpiryField';

function getDefaultValues(cves: string[], scopeContext: ScopeContext): ExceptionValues {
    const imageScope =
        scopeContext === 'GLOBAL'
            ? { registry: ALL, remote: ALL, tag: ALL }
            : {
                  registry: scopeContext.imageName.registry,
                  remote: scopeContext.imageName.remote,
                  tag: ALL,
              };

    return { cves, comment: '', scope: { imageScope } };
}
export type ExceptionRequestFormProps = {
    cves: CveSelectionsProps['cves'];
    scopeContext: ScopeContext;
    onSubmit: (formValues: ExceptionValues, helpers: FormikHelpers<ExceptionValues>) => void;
    onCancel: () => void;
    formHeaderText: string;
    commentFieldLabel: string;
    validationSchema: yup.ObjectSchema<ExceptionValues>;
    showExpiryField: boolean;
    showScopeField: boolean;
};

function ExceptionRequestForm({
    cves,
    scopeContext,
    onSubmit,
    onCancel,
    formHeaderText,
    commentFieldLabel,
    validationSchema,
    showExpiryField,
    showScopeField,
}: ExceptionRequestFormProps) {
    const [activeKeyTab, setActiveKeyTab] = useState<string | number>('options');

    const formik = useFormik({
        initialValues: getDefaultValues(
            cves.map(({ cve }) => cve),
            scopeContext
        ),
        onSubmit,
        validationSchema,
    });

    const {
        handleBlur,
        setFieldValue,
        touched,
        handleSubmit,
        submitForm,
        isSubmitting,
        isValid,
        errors,
    } = formik;

    function onAddCVE(cve: string) {
        return formik.setValues((values) => {
            const prevCVEs = values.cves;
            return {
                ...values,
                cves: [...prevCVEs, cve],
            };
        });
    }

    function onRemoveCVE(cve: string) {
        return formik.setValues((values) => {
            const prevCVEs = values.cves;
            return {
                ...values,
                cves: prevCVEs.filter((prevCVE) => prevCVE !== cve),
            };
        });
    }

    return (
        <>
            <Form
                onSubmit={handleSubmit}
                className="pf-v5-u-display-flex pf-v5-u-flex-direction-column"
                style={{ minHeight: 0 }}
            >
                <Tabs
                    className="pf-v5-u-flex-shrink-0"
                    activeKey={activeKeyTab}
                    onSelect={(_, tab) => setActiveKeyTab(tab)}
                >
                    <Tab eventKey="options" title="Options" tabContentId="options" />
                    <Tab eventKey="cves" title="CVE selections" tabContentId="cves" />
                </Tabs>
                <TabContent
                    id="options"
                    className="pf-v5-u-flex-1"
                    hidden={activeKeyTab !== 'options'}
                >
                    <Flex
                        direction={{ default: 'column' }}
                        spaceItems={{ default: 'spaceItemsLg' }}
                    >
                        <Text>{formHeaderText}</Text>
                        {showExpiryField && <ExpiryField formik={formik} />}
                        {showScopeField && (
                            <ExceptionScopeField
                                fieldId="scope"
                                label="Scope"
                                formik={formik}
                                scopeContext={scopeContext}
                            />
                        )}
                        <FormGroup fieldId="comment" label={commentFieldLabel} isRequired>
                            <TextArea
                                id="comment"
                                name="comment"
                                isRequired
                                onBlur={handleBlur('comment')}
                                onChange={(_event, value) => setFieldValue('comment', value)}
                                validated={touched.comment && errors.comment ? 'error' : 'default'}
                            />
                        </FormGroup>
                    </Flex>
                </TabContent>
                <TabContent
                    id="cves"
                    className="pf-v5-u-flex-1"
                    hidden={activeKeyTab !== 'cves'}
                    style={{ overflowY: 'auto' }}
                >
                    <CveSelections
                        cves={cves}
                        selectedCVEIds={formik.values.cves}
                        onAdd={onAddCVE}
                        onRemove={onRemoveCVE}
                    />
                </TabContent>
                <Flex>
                    <Button
                        isLoading={isSubmitting}
                        isDisabled={isSubmitting || !isValid}
                        onClick={submitForm}
                    >
                        Submit request
                    </Button>
                    <Button isDisabled={isSubmitting} variant="secondary" onClick={onCancel}>
                        Cancel
                    </Button>
                </Flex>
            </Form>
        </>
    );
}

export default ExceptionRequestForm;
